package ntd.util.frame.task.handle.data;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import com.tool.ToolRedisson;
import ntd.task.Task;
import ntd.task.bo.TaskInfo;
import ntd.util.UtilCatch;
import ntd.util.frame.javacv.bo.FactorStandardBean;
import ntd.util.frame.javacv.bo.WaterBean;
import ntd.util.frame.javacv.factory.FactoryAiDataSite;
import ntd.util.frame.javacv.factory.FactoryWaterStandard;
import ntd.util.util.ToolDuration;

import java.util.HashMap;
import java.util.Map;

public class TaskDataForecast implements Task {
    public static final String NAME = "任务-数据预测同步任务";

    @Override
    public TaskInfo info() {
        return new TaskInfo(NAME, "task-data-data-forecast", new TaskDataForecast());
    }

    @Override
    public void execute(Object o) {
        ToolDuration.duration(this::handle, NAME);
    }

    public void handle() {
        //每天凌晨1点开始执行任务
//        CronUtil.schedule("0 0 1 * * ?", (Runnable) () -> {
        Map<String, String> siteMap = FactoryAiDataSite.initSiteList();
        //站点列表，包含mn，名称
        for (String mn : siteMap.keySet()) {
            //每个站点开启一个线程，同时不超过5个，防止服务器崩溃
            ThreadUtil.execute(() -> {
                UtilCatch.tryCatchNoRes(() -> {
                    //请求Ai服务器
                    Map<String, Object> bodyMap = new HashMap<>();
                    bodyMap.put("station", siteMap.getOrDefault(mn, "黄庄桥"));
                    bodyMap.put("tspan", 168);
                    bodyMap.put("rtime", DateUtil.today() + " 00:00:00");
                    String result1 = HttpUtil.post("49.232.109.39:8009/Water_Predict", JSONUtil.toJsonStr(bodyMap));
                    StaticLog.info(result1);

                    int status = JSONUtil.parseObj(result1).getInt("status");
                    if (status == 1) {//返回数据不正确
                        return;
                    }
                    String data = JSONUtil.parseObj(result1).getStr("message");

                    JSONObject objectFactor = JSONUtil.parseObj(data);
                    StaticLog.info("所有因子==" + objectFactor.keySet());

                    Map<String, Integer> siteLevelMap = new HashMap<>();
                    //计算各个因子的水质标准：默认是一类标准
                    for (String factor : objectFactor.keySet()) {

                        if (factor.contains("电导率") || factor.contains("浊度")) continue;//由于水质每个分类都相同

                        //因子数据按天分组
                        String factorValue = objectFactor.getStr(factor);
                        JSONObject objectValue = JSONUtil.parseObj(factorValue);
                        //因子的总数据
                        int size = objectValue.keySet().size();
                        //计算每一天的平均值
                        String dateInit = "";
                        int dateNum = 0, allNum = 0;
                        double valueAll = 0;
                        for (String date : objectValue.keySet()) {
                            allNum++;
                            //处理同一天的数据
                            if (StrUtil.equals(date.split(" ")[0], dateInit)) {
                                valueAll = NumberUtil.add(valueAll, objectValue.getDouble(date).doubleValue());
                                dateNum++;
                                //最后一组的值
                                if (allNum == size) {
                                    double dateValue = NumberUtil.div(valueAll, dateNum);

                                    int dateLevel = getFactorLevel(factor, dateValue);
                                    StaticLog.info(factor + "===" + dateInit + "--" + dateValue + "--" + dateLevel);

                                    if (siteLevelMap.getOrDefault(dateInit, 0) < dateLevel) {
                                        siteLevelMap.put(dateInit, dateLevel);
                                    }
                                }
                            } else {
                                //计算上一组的值
                                if (!StrUtil.isEmpty(dateInit)) {
                                    double dateValue = NumberUtil.div(valueAll, dateNum);

                                    int dateLevel = getFactorLevel(factor, dateValue);
                                    StaticLog.info(factor + "===" + dateInit + "--" + dateValue + "--" + dateLevel);

                                    if (siteLevelMap.getOrDefault(dateInit, 0) < dateLevel) {
                                        siteLevelMap.put(dateInit, dateLevel);
                                    }
                                }

                                dateNum = 1;
                                valueAll = objectValue.getDouble(date);
                            }
                            dateInit = date.split(" ")[0];

                        }

                    }

                    StaticLog.info(siteMap.getOrDefault(mn, "黄庄桥")+"站点每天的水质==" + JSONUtil.toJsonStr(siteLevelMap));
                    //连接redis
                    //存站点数据预测的请求数据，day表示当天请求日期
                    ToolRedisson.me(0).set(StrUtil.format("data:forecast:value:{}:{}", mn, DateUtil.today()), data);
                    //存站点的预测水质数据，day表示日期
                    for (String date : siteLevelMap.keySet()) {
                        ToolRedisson.me(0).set(StrUtil.format("data:forecast:level:{}:{}", mn, date), siteLevelMap.getOrDefault(date, 1) + "");
                    }
                });
            });

            //每个站点运行间隔1分钟，防止过多服务器崩溃
            ThreadUtil.safeSleep(90*1000);
        }
    }

    public static int getFactorLevel(String factor, double factorValue24) {

        int currentFactorLevel = 1;
        try {
            //水质类别
            level_for:for (WaterBean waterBean : FactoryWaterStandard.initWaterStandardBeans()) {
                //因子标准值
                for (FactorStandardBean factorStandardBean : waterBean.getFactorStandardBeans()) {

                    if (StrUtil.contains(factor, factorStandardBean.getFactorName())) {
                        if (factorStandardBean.getOMin() == 0) {//其他因子
                            if (StrUtil.contains(factor, "溶解氧")) {//溶解氧排序规则跟其他因子相反
                                if (factorValue24 <= factorStandardBean.getOMax() ) {
                                    currentFactorLevel = waterBean.getLevelNum();//当前的水质类别
                                }
                            } else {
                                //符合最后一组直接赋值
                                if (factorValue24 <= factorStandardBean.getOMax() || waterBean.getLevelNum() ==  5) {
                                    currentFactorLevel = waterBean.getLevelNum();//当前的水质类别
                                    break level_for;//跳出水质循环，进行下一个因子
                                }

                            }

                        } else {//ph，含有上下限
                            if (factorValue24 >= factorStandardBean.getOMin() && factorValue24 <= factorStandardBean.getOMax()) {
                                currentFactorLevel = waterBean.getLevelNum();//当前的水质类别
                                break level_for;//跳出水质循环，进行下一个因子
                            }
                        }
                    }

                }

            }


        } catch (Exception e) {
            e.printStackTrace();
        }
        return currentFactorLevel;
    }

    public static void main(String[] args) {
        new TaskDataForecast().execute(null);
    }
}
